// --- 0. 模拟不同的库文件 ---
// 在实际开发中，这些扩展会放在不同的 .dart 文件中。
// 这里为了整合演示，将它们都放在同一个文件里。

// --- 模拟 'string_apis.dart' ---
// 定义一个名为 NumberParsing1 的扩展，作用于 String
extension NumberParsing1 on String {
  // 添加一个 parseInt 方法
  int parseInt() {
    print("(来自 NumberParsing1)");
    return int.parse(this); // 'this' 指向 String 实例本身
  }

  // 添加一个 parseDouble 方法
  double parseDouble() {
    print("(来自 NumberParsing1)");
    return double.parse(this);
  }
}

// --- 模拟 'string_apis_2.dart' ---
// 定义另一个扩展，与 NumberParsing1 存在同名方法 parseInt
extension NumberParsing2 on String {
  int parseInt() {
    print("(来自 NumberParsing2 - 不同的实现或来源)");
    // 可能有不同的实现，这里简单返回
    return int.parse(this) + 100; // 假设实现不同
  }
}

// --- 模拟 'string_apis_3.dart' ---
// 修正：将原来重名的 NumberParsing1 改名为 NumberParsing3，解决 duplicate_definition 错误
extension NumberParsing3 on String {
  // <--- 已重命名
  int parseInt() {
    print("(来自 NumberParsing3)"); // <--- 更新来源说明
    return int.parse(this) * 2; // 又一个不同的实现
  }

  // 这个扩展还额外定义了 parseNum
  num parseNum() {
    print("(来自 NumberParsing3)"); // <--- 更新来源说明
    return num.parse(this);
  }
}

// --- 模拟本地库中的未命名扩展 ---
// 未命名扩展仅在当前库可见
extension on String {
  // 添加一个 getter 判断字符串是否为空白
  bool get isBlank => trim().isEmpty;
}

// --- 模拟泛型扩展 ---
// 定义一个作用于 List<T> 的泛型扩展
extension MyFancyList<T> on List<T> {
  // 获取双倍长度的 getter
  int get doubleLength => length * 2;

  // 定义一个一元操作符 '-' 返回列表的逆序副本
  List<T> operator -() => reversed.toList();

  // 定义一个方法，将列表在指定位置分割成两个列表
  List<List<T>> split(int at) {
    if (at < 0 || at > length) {
      throw ArgumentError('Index out of range: $at');
    }
    return [sublist(0, at), sublist(at)];
  }
}

// --- Main Function ---
void main() {
  print('--- 1. 演示基本扩展方法使用 ---');
  String numberString = '42';
  // 修正：直接调用 '42'.parseInt() 会产生歧义 (ambiguous)，因为 NumberParsing1 和 NumberParsing2 都定义了它。
  // 我们在后面的冲突处理部分演示如何解决。这里先注释掉或使用明确的扩展。
  // print('"$numberString".parseInt() = ${numberString.parseInt()}'); // <--- 注释掉，避免歧义

  // parseDouble 没有歧义，可以正常调用 (只有 NumberParsing1 定义了它)
  print('"3.14".parseDouble() = ${"3.14".parseDouble()}');
  print('');

  print('--- 2. 演示静态类型 vs dynamic ---');
  // 扩展方法依赖静态类型解析
  var v = '2'; // v 的静态类型被推断为 String
  // 因为上面注释掉了隐式调用，这里为了演示，我们显式调用 NumberParsing1 的 parseInt
  print(
    'var v = "$v"; (显式调用 NumberParsing1) v.parseInt() = ${NumberParsing1(v).parseInt()}',
  ); // OK

  dynamic d = '2'; // d 的静态类型是 dynamic
  print('\ndynamic d = "$d"; 尝试调用 d.parseInt()...');
  try {
    // 在 dynamic 类型上调用扩展方法会在运行时抛出 NoSuchMethodError
    // 即使我们知道它应该有 parseInt，但动态类型无法静态解析到扩展方法
    d.parseInt(); // <--- 修正：使用正确的变量名 d
  } catch (e) {
    print('捕获到错误: $e');
    print('结论：不能在 dynamic 类型的变量上直接调用扩展方法。');
  }
  print('');

  print('--- 3. 演示 API 冲突处理 ---');
  // 当导入多个库，且它们包含相同签名的扩展方法时，会产生冲突。

  // a) 使用 hide/show (概念演示)
  print('a) 使用 hide/show (概念):');
  print("   // import 'string_apis_2.dart' hide NumberParsing2;");
  print('   // 通过 hide 隐藏冲突的扩展，然后可以正常调用未隐藏的那个。');
  print('   // 这里因为都在一个文件，无法实际演示 hide，但原理如此。');
  print('   // 假设隐藏了 NumberParsing2，则调用的是 NumberParsing1 的：');
  print('   (模拟调用) \'42\'.parseInt() -> ${NumberParsing1('42').parseInt()}');
  print('');

  // b) 显式应用扩展 (当扩展名称不同时)
  print('b) 显式应用扩展 (名称不同):');
  // print('42'.parseInt()); // 这会报错，因为编译器不知道用哪个 parseInt (NumberParsing1 vs NumberParsing2)
  print('   调用 NumberParsing1: ${NumberParsing1('42').parseInt()}');
  print('   调用 NumberParsing2: ${NumberParsing2('42').parseInt()}');
  print('');

  // c) 显式应用扩展 (当扩展名称相同时 - 模拟前缀导入)
  print('c) 显式应用扩展 (名称相同 - 模拟前缀):');
  // 之前这里有两个 NumberParsing1，现在第二个改名为 NumberParsing3
  // print('42'.parseInt()); // 仍然会报错 (NumberParsing1 vs NumberParsing2)
  print("   // 假设: import 'string_apis_3.dart' as rad; (现在对应 NumberParsing3)");
  print('   调用第一个 NumberParsing1: ${NumberParsing1('42').parseInt()}');
  // 修正：使用重命名后的 NumberParsing3
  print(
    '   调用 NumberParsing3 (模拟 rad.NumberParsing): ${NumberParsing3('42').parseInt()}',
  );
  // 修正：调用 NumberParsing3 的 parseNum 方法
  print(
    '   调用 NumberParsing3 的 parseNum: ${NumberParsing3('42').parseNum()}',
  ); // 只有 NumberParsing3 定义了 parseNum
  print('');

  print('--- 4. 演示未命名扩展 ---');
  String emptyString = "   ";
  String nonEmptyString = " hello ";
  print('"$emptyString".isBlank = ${emptyString.isBlank}'); // true
  print('"$nonEmptyString".isBlank = ${nonEmptyString.isBlank}'); // false
  print('');

  print('--- 5. 演示泛型扩展 ---');
  List<int> numbers = [1, 2, 3, 4, 5];
  print('原始列表: $numbers');
  print('列表的双倍长度: ${numbers.doubleLength}'); // 调用 getter
  print('列表取反 (-): ${-numbers}'); // 调用操作符
  print('在索引 2 处分割列表: ${numbers.split(2)}'); // 调用方法

  List<String> words = ["apple", "banana", "cherry"];
  print('\n原始列表: $words');
  print('列表的双倍长度: ${words.doubleLength}');
  print('列表取反 (-): ${-words}');
  print('在索引 1 处分割列表: ${words.split(1)}');
  print('');

  print('--- 所有扩展方法演示完成 ---');
}
